﻿using BlazorAppWithCookieAuth.Client;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Server;
using Microsoft.AspNetCore.Components;
using System.Diagnostics;
using System.Security.Claims;
using Microsoft.AspNetCore.Components.Web;

namespace BlazorAppWithCookieAuth;

public class CookieServerAuthenticationStateProvoider : ServerAuthenticationStateProvider, IDisposable
{
    private readonly PersistentComponentState _state;
    private readonly PersistingComponentStateSubscription _subscription;
    private Task<AuthenticationState>? authenticationStateTask;

    public CookieServerAuthenticationStateProvoider(PersistentComponentState serverState)
    {
        _state = serverState;
        AuthenticationStateChanged += OnAuthenticationStateChanged;

        _subscription = _state.RegisterOnPersisting(OnPersistingAsync, RenderMode.InteractiveWebAssembly);
    }
    private async Task OnPersistingAsync()
    {
        if (authenticationStateTask is null)
        {
            throw new UnreachableException($"Authentication state not set in {nameof(OnPersistingAsync)}().");
        }

        var authenticationState = await authenticationStateTask;
        var principal = authenticationState.User;

        if (principal.Identity?.IsAuthenticated == true)
        {
            var userId = principal.FindFirst(ClaimTypes.NameIdentifier)?.Value;
            var givenName = principal.FindFirst(ClaimTypes.GivenName)?.Value;

            if (userId != null && givenName != null)
            {
                _state.PersistAsJson(nameof(UserInfo), new UserInfo
                {
                    UserName = userId,
                    GivenName = givenName
                });
            }
        }
    }
    private void OnAuthenticationStateChanged(Task<AuthenticationState> task)
    {
        authenticationStateTask = task;
    }
    public void Dispose()
    {
        _subscription.Dispose();
        AuthenticationStateChanged -= OnAuthenticationStateChanged;
    }
}
